package com.chuenyee;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.FileSystemResourceLoader;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import javax.sql.DataSource;
import java.security.KeyFactory;
import java.security.KeyPair;


@SuppressWarnings("all")
@Configuration
@EnableAuthorizationServer
public class UAAServerConfig {

    private  static  final  int ACCESSTOKENVALIDITYSENCONDS = 7200;
    private  static  final  int EWFRESHTOKENVALIDITYSENCONDS = 7200;

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;

//    @Autowired
//    privat
//    e RedisConnectionFactory connectionFactory;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

 //   @Autowired
 //   private UserDetailsService userDetailsService;

    @Bean
    public TokenStore tokenStore(){
        //数据库存储Token
        //return new JdbcTokenStore(dataSource);
        //redis存储Token
        //return new RedisTokenStore(connectionFactory);
        //JWT
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

        /*
        *  配置客户端
        * */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource).withClient("client_1").secret(passwordEncoder().encode("123456"))
                    .redirectUris("http://www.baidu.com").authorizedGrantTypes("authorization_code","password","refresh_token").scopes("all")
                    .accessTokenValiditySeconds(ACCESSTOKENVALIDITYSENCONDS)
                    .refreshTokenValiditySeconds(EWFRESHTOKENVALIDITYSENCONDS);
//            clients.withClientDetails(redisClientDetailsService);
//            redisClientDetailsService.loadAllClientToCache();
        }

        /*
        *  Token的存储问题
        * */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints){
            endpoints
                    .tokenStore(tokenStore())
                    .authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService());

            if (tokenStore() instanceof JwtTokenStore) {
                endpoints.accessTokenConverter(jwtAccessTokenConverter);
            }

//            endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
//            endpoints.userDetailsService(userDetailsService());
        }

        /*
         * 允许哪些客户端登陆访问
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer){
           oauthServer.allowFormAuthenticationForClients();
           oauthServer.checkTokenAccess("permitAll()");
        }



        @Bean
        PasswordEncoder passwordEncoder(){
            PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            return  passwordEncoder;
        }

        @Bean
        AuthenticationManager authenticationManager(){
            AuthenticationManager authenticationManager = new AuthenticationManager() {
                public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                    return daoAuthenticationProvider().authenticate(authentication);
                }
            };
            return authenticationManager;
        }

        @Bean
        public AuthenticationProvider daoAuthenticationProvider(){
            DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
            daoAuthenticationProvider.setUserDetailsService(userDetailsService());
            daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
            daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
            return  daoAuthenticationProvider;
        }

        @Bean
         UserDetailsService userDetailsService(){
            InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
            userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456"))
                    .authorities("admin").build());
            return  userDetailsService;
        }

        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(){
            JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();

            //  jwtAccessTokenConverter.setSigningKey("chuenyee-oauth2.0"); // 对称加密
            //非对称加密
            ClassPathResource resource = new ClassPathResource("jcy-jwt.jks");
            KeyStoreKeyFactory kayStoryKeyFactory = new KeyStoreKeyFactory(resource,"jcy123".toCharArray());
            KeyPair keyPair = kayStoryKeyFactory.getKeyPair("jcy-jwt");

            jwtAccessTokenConverter.setKeyPair(keyPair);
            return  jwtAccessTokenConverter;
        }
    }
}
